﻿using System.Collections.Generic;
using System.Drawing;

namespace SellAvi.Classes
{
    /// <summary>
    /// Спасибо недописанному коду https://habrahabr.ru/post/239803/
    /// </summary>
    public class OpticalRecognition
    {
        private Bitmap _image;
        private List<CharInfo> _charInfoDictionary;
        public OpticalRecognition(string fileToOCRe)
        {
            _image = (Bitmap)Image.FromFile(fileToOCRe, true);

            //StringBuilder sb = new StringBuilder();
            //foreach (var charInfo in charsToRecognize)
            //    sb.Append(charInfo.Char);

            //textBox1.Text = sb.ToString();
            //return "";
        }

        void RemoveAlphaChannel(Bitmap src)
        {
            for (int y = 0; y < src.Height; y++)
                for (int x = 0; x < src.Width; x++)
                {
                    var pxl = src.GetPixel(x, y);
                    if (pxl.A == 0) src.SetPixel(x, y, Color.FromArgb(255, 255, 255, 255));
                }

        }
        private Bitmap CropImage(Bitmap sourceBitmap)
        {
            var upperLeft = GetCorner(sourceBitmap, true);
            var lowerRight = GetCorner(sourceBitmap, false);
            //var width = lowerRight.X - upperLeft.X;
            //var height = lowerRight.Y - upperLeft.Y;

            //Bitmap target = new Bitmap(width, height);
            Bitmap target = new Bitmap(8, 10);

            using (Graphics g = Graphics.FromImage(target))
            {
                //что такое ul?
                var ul = new Point(0,0);
                g.DrawImage(sourceBitmap, new Rectangle(0, 0, target.Width, target.Height), new Rectangle(ul, new Size(8, 10)), GraphicsUnit.Pixel);
            }

            return target;
        }


        /// <summary>
        /// fake
        /// </summary>
        /// <param name="img"></param>
        /// <param name="bl"></param>
        /// <returns></returns>
        private Point GetCorner(Image img, bool bl)
        {
            if (bl)
            {
                new Point(8, 10);
            }
            return new Point(10,8);
        }

        /// <summary>
        /// fake
        /// </summary>
        /// <param name="bitmapPattern"></param>
        /// <returns></returns>
        private List<CharInfo> CropChars(Bitmap bitmapPattern)
        {
            return null;
        }

        private void CropChars(Bitmap bitmapPattern, string stringPattern)
        {
            var croped = CropImage(bitmapPattern);

            RemoveAlphaChannel(croped);

            int cntr = 0;

            for (int x = 0; x < croped.Width; x++)
            {
                for (int y = 0; y < croped.Height; y++)
                {

                    if (
                       (y == croped.Height - 1 && x > 0)
                       || (x == croped.Width - 1 && x > 0)
                       )
                    {
                        var rect = new Rectangle(0, 0, x, croped.Height);

                        //Дубли пропускаем
                        //if (_charInfoDictionary.FirstOrDefault(c => c.Char == stringPattern[cntr]) == null)
                        //    _charInfoDictionary.Add(new CharInfo(CropImage(croped, rect), stringPattern[cntr]));

                        ++cntr;

                        if (croped.Width - x <= 1) return;

                        croped = CropImage(croped, new Rectangle(x, 0, croped.Width - x, croped.Height));
                        x = 0;
                    }

                    if (!IsEmptyPixel(croped.GetPixel(x, y)))
                    {
                        break;
                    }
                }

            }

        }

        /// <summary>
        /// fake
        /// </summary>
        /// <param name="bm"></param>
        /// <param name="rect"></param>
        /// <returns></returns>
        private Bitmap CropImage(Bitmap bm, Rectangle rect)
        {
            return _image;
        }

        /// <summary>
        /// fake
        /// </summary>
        /// <param name="c"></param>
        /// <returns></returns>
        private bool IsEmptyPixel(Color c)
        {
            return c.IsEmpty;
        }

        public IEnumerable<CharInfo> Recognize()
        {
            var bitmap = _image;
            RemoveAlphaChannel(bitmap);

            var charsToRecognize = CropChars(bitmap);

            List<CharInfo> result = new List<CharInfo>();

            foreach (var charInfo in charsToRecognize)
            {
                CharInfo closestChar = null;

                int maxMatches = 0;

                foreach (var dictItem in _charInfoDictionary)
                {
                    var matches = dictItem.Compare(charInfo);

                    if (matches > maxMatches)
                    {
                        maxMatches = matches;
                        closestChar = dictItem;
                    }


                }
                result.Add(closestChar);

            }
            return result;
        }
    }


    public class CharInfo
    {

        //Последовательность яркостей
        public int[] _hsbSequence;

        //Кол-во областей, на которые будут разделены символы, для составления последовательности яркостей (по горизонтали и вертикали)
        private const int XPoints = 4;
        private const int YPoints = 4;

        //Символьное представление сущности
        public char Char { get; set; }

        //Графическое представление сущности
        public Bitmap CharBitmap { get; private set; }

        public CharInfo(Bitmap charBitmap, char letter)
        {
            Char = letter;

            CharBitmap = charBitmap;

            //Сжимаем наш символ в соответствии с кол-вом областей
            Bitmap resized = new Bitmap(charBitmap, XPoints, YPoints);

            _hsbSequence = new int[XPoints * YPoints];

            int i = 0;

            //И заполняем последовательность яркостями*10. Сама яркость, это double от 0.0(черное) до 1.0(белое)
            for (int y = 0; y < YPoints; y++)
                for (int x = 0; x < XPoints; x++)
                    _hsbSequence[i++] = (int)(resized.GetPixel(x, y).GetBrightness() * 10);

        }

        /// <summary>
        /// Метод сравнения с другим символом, сравнивает последовательности яркостей
        /// </summary>
        /// <param name="charInfo"></param>
        /// <returns>Количество совпадений</returns>
        public int Compare(CharInfo charInfo)
        {
            int matches = 0;

            for (int i = 0; i < _hsbSequence.Length; i++)
            {
                if (_hsbSequence[i] == charInfo._hsbSequence[i]) ++matches;
            }

            return matches;
        }
    }

}
